<template>
  <div class="index-container">
    <el-input v-model.trim="state.domain" placeholder="请输入ASN/IP/域名" @keyup.enter="search()" clearable>
      <template #prepend>ASN/IP/域名</template>
      <template #append>
        <el-button @click="search()" :loading="state.loading">查询</el-button>
      </template>
    </el-input>

    <el-alert v-if="state.ip!==''" effect="dark" :closable="false">
      <template #title>
        您当前的ip是:{{ state.ip }},来自&nbsp;{{ state.address }}。
      </template>
    </el-alert>
    <div class="result" v-loading="state.loading">
      <el-descriptions v-if="state.showResult" title="查询结果" :column="1" border>
        <template #extra>
          <el-link type="primary" @click.prevent="exportToExcel()">导出Excel</el-link>
        </template>
        <el-descriptions-item label="IP地址:">{{ state.ipInfo.ip }}</el-descriptions-item>
        <el-descriptions-item label="地理位置运营商:">{{ state.ipInfo.addr }}</el-descriptions-item>
        <el-descriptions-item label="RBL状态:">{{ state.ipInfo.rbl }}</el-descriptions-item>
        <el-descriptions-item label="运营公司:">{{ state.ipInfo.operating_company }}</el-descriptions-item>
        <el-descriptions-item label="归属公司:">{{ state.ipInfo.affiliated_company }}</el-descriptions-item>
        <el-descriptions-item label="网络类型:">{{ state.ipInfo.network_type }}</el-descriptions-item>
        <el-descriptions-item label="ASN号码:">{{ state.ipInfo.asn }}</el-descriptions-item>
        <el-descriptions-item label="反向DNS:">{{ state.ipInfo.dns }}</el-descriptions-item>
        <el-descriptions-item label="RIR机构:">{{ state.ipInfo.rir }}</el-descriptions-item>
        <el-descriptions-item label="国家地区:">{{ state.ipInfo.country }}</el-descriptions-item>
        <el-descriptions-item label="省份/州:">{{ state.ipInfo.province }}</el-descriptions-item>
        <el-descriptions-item label="城市:">{{ state.ipInfo.city }}</el-descriptions-item>
        <el-descriptions-item label="邮政编码:">{{ state.ipInfo.postcode }}</el-descriptions-item>
        <el-descriptions-item label="经纬度:">{{ state.ipInfo.latitude_longitude }}</el-descriptions-item>
      </el-descriptions>
      <el-descriptions v-if="state.showResult" direction="vertical" :column="1" border>
        <el-descriptions-item label="IP Whois 信息:">
          <pre>
            {{ state.ipInfo.whois }}
          </pre>
        </el-descriptions-item>
      </el-descriptions>
      <h4 v-if="state.showResult" class="mapTitle">IP 地图定位</h4>
      <div id="map"></div>
    </div>
    <div class="verify-container" v-show="state.showVerify" @click.self="state.showVerify=false">
      <div id="verify"></div>
    </div>
  </div>
</template>

<script setup>
import FileSaver from 'file-saver'
import XLSX from 'xlsx'
import { reactive, getCurrentInstance } from 'vue'

const { proxy } = getCurrentInstance()

const state = reactive({
  domain: '',
  ip: '',
  address: '',
  showResult: false,
  loading: false,
  ipInfo: {},
  showVerify:false
})

const getIp = () => {
  proxy.$http.get('/getip').then(res => {
    state.ip = res.data.ip
    state.domain = res.data.ip
    state.address = res.data.address
  }).catch(err => {
    proxy.$message.error('网络异常,请刷新后重试！')
  })
}
getIp()

// const ipReg = /^((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$|^([\da-fA-F]{1,4}:){6}((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$|^::([\da-fA-F]{1,4}:){0,4}((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$|^([\da-fA-F]{1,4}:):([\da-fA-F]{1,4}:){0,3}((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$|^([\da-fA-F]{1,4}:){2}:([\da-fA-F]{1,4}:){0,2}((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$|^([\da-fA-F]{1,4}:){3}:([\da-fA-F]{1,4}:){0,1}((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$|^([\da-fA-F]{1,4}:){4}:((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$|^([\da-fA-F]{1,4}:){7}[\da-fA-F]{1,4}$|^:((:[\da-fA-F]{1,4}){1,6}|:)$|^[\da-fA-F]{1,4}:((:[\da-fA-F]{1,4}){1,5}|:)$|^([\da-fA-F]{1,4}:){2}((:[\da-fA-F]{1,4}){1,4}|:)$|^([\da-fA-F]{1,4}:){3}((:[\da-fA-F]{1,4}){1,3}|:)$|^([\da-fA-F]{1,4}:){4}((:[\da-fA-F]{1,4}){1,2}|:)$|^([\da-fA-F]{1,4}:){5}:([\da-fA-F]{1,4})?$|^([\da-fA-F]{1,4}:){6}:$/

const urlReg = /^(((ht|f)tps?):\/\/)?[\w-]+(\.[\w-]+)+([\w.,@?^=%&:/~+#-]*[\w@?^=%&/~+#-])?$/
const search = () => {
  if (state.domain === '') {
    return proxy.$message.error('输入不能为空！')
  }else{
    state.domain = state.domain.replace((state.domain).match(urlReg)[1],'').replace((state.domain).match(urlReg)[5],'')
  }
  startSearch()
}

const startSearch = ()=>{
  state.showVerify = true
  AWSC.use('nc', function (state1, module) {
    if(window.nc){
      return window.nc.reset()
    }
    window.nc = module.init({
      appkey: 'FFFF0N00000000009A78',
      scene: 'nc_other',
      renderTo: 'verify',
      success: function (data) {
        state.loading = true
        state.showVerify = false
        proxy.$http.post('/captcha',{
          csessionId: data.sessionId,
          sig: data.sig,
          ctoken: data.token
        }).then(res=>{
          if(res.data.code === 0){
            proxy.$http.post('/ip',{
              domain: state.domain,
              token:res.data.data[0]
            }).then(res => {
              if (res.status === 200) {
                state.loading = false
                state.showResult = true
                state.ipInfo = res.data
                state.ipInfo.whois = window.atob(res.data.whois)
                const latitude = (state.ipInfo.latitude_longitude).split('|')[0]
                const location = latitude.split(/[ / ]/).filter(item => item).reverse()
                document.querySelector('#map').style.display = 'block'

                const map = new BMap.Map('map') // 创建Map实例
                const point = new BMap.Point(location[0], location[1]) // 坐标点
                map.centerAndZoom(point, 15) // 初始化地图,设置中心点坐标和地图级别
                const marker = new BMap.Marker(point) // 绘制中心点标注
                map.addOverlay(marker) // 添加中心点到地图中
                map.enableScrollWheelZoom() // 开启鼠标滚轮缩放地图
                const opts = {
                  title: "IP: "+res.data.ip, // 信息窗口标题
                }
                const content = `${res.data.addr}<br/>经纬度:${location}`
                const infoWindow = new BMap.InfoWindow(content,opts) // 创建信息窗口对象
                marker.addEventListener('click',()=>{
                  map.openInfoWindow(infoWindow, marker.getPosition()) // 打开信息窗口
                })
              }
            }).catch(err => {
              state.loading = false
              proxy.$message.error('输入有误或网络异常,请检查是否输入正确后重试！')
            })
          }
        }).catch(err=>{
          state.loading = false
          proxy.$message.error('网络异常,请刷新后重试！')
        })
      },
      // 滑动验证失败时触发该回调参数。
      fail: function (failCode) {
        window.console && console.log(failCode)
      },
      // 验证码加载出现异常时触发该回调参数。
      error: function (errorCode) {
        window.console && console.log(errorCode)
      }
    })
  })
}
//导出Excel
const exportToExcel = () => {
  let et = XLSX.utils.table_to_book(document.querySelector('.result')) //此处传入table的DOM节点
  let etout = XLSX.write(et, {
    bookType: 'xlsx',
    bookSST: true,
    type: 'array'
  })
  try {
    FileSaver.saveAs(new Blob([etout], {
      type: 'application/octet-stream'
    }), 'ipInfo.xlsx')
  } catch (err) {}
  return etout
}
</script>

<style lang="less" scoped>
.index-container {
  max-width: 1000px;
  margin: 0 auto;
  padding: 15px;

  /deep/ .el-input {
    .el-input__inner {
      box-sizing: border-box;

      &:focus {
        background-color: #fff;
        border: 2px solid #346cb0;
        outline: 0;
      }
    }

    .el-input-group__prepend {
      padding-left: 10px;
      padding-right: 10px;
    }

    .el-button {
      background-color: #346cb0;
      color: #fff;
      border-bottom-left-radius: unset;
      border-top-left-radius: unset;

      &:hover {
        background-color: #2b5a92;
      }
    }
  }

  .el-alert,
  .result,
  #map {
    margin-top: 15px;
  }

  .el-alert {
    background-color: #346cb0;
  }

  .result {
    background-color: transparent;
    //min-height: 500px;
    .mapTitle{
      color: #606266;
      font-size: 16px;
      margin: 15px 0;
    }
    #map {
      height: 500px;
      width: 100%;
      display: none;
    }

    /deep/ .el-descriptions {
      border-radius: 10px;
      &:nth-of-type(1) {
        .el-descriptions__body {
          table {
            tbody {
              tr{
                &:nth-last-of-type(1){
                  td {
                    border-bottom: none;
                  }
                }
              }
            }
          }
        }
      }
      .el-descriptions__header {
        margin-bottom: 15px;

        .el-descriptions__title {
          color: #606266;
        }
      }
    }
  }
  .verify-container{
    width: 100%;
    height: 100vh;
    background-color: rgba(0,0,0,0.2);
    position: fixed;
    top: 0;
    left: 0;
    z-index: 999999;
    #verify{
      position: relative;
      top: 30%;
      display: flex;
      align-items: center;
      justify-content: center;
    }
  }
}
</style>
